﻿using Microsoft.Extensions.Logging;
using System.Net;
using System.Net.Sockets;
using TcpJsonService.Core;

namespace TcpJsonService.Json
{
    /// <summary>
    /// 模拟雾灯通道
    /// </summary>
    public class VirtualJsonControllerChannel : TcpChannel
    {
        /// <summary>
        /// 线程类
        /// </summary>
        private readonly Task _task;

        /// <summary>
        /// 线程取消功能
        /// </summary>
        private readonly CancellationTokenSource _source = new();

        /// <summary>
        /// 控制器编号
        /// </summary>
        private readonly int _controllerId;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="remoteEndPoint">远程地址</param>
        /// <param name="logger">日志</param>
        /// <param name="controllerId">控制器编号</param>
        public VirtualJsonControllerChannel(IPEndPoint remoteEndPoint, ILogger logger, int controllerId) : base(remoteEndPoint, logger)
        {
            _controllerId = controllerId;
            _task = new Task(SendWeather, _source.Token);
            _task.Start();
        }

        private void SendWeather()
        {
            while (!_source.IsCancellationRequested)
            {
                Thread.Sleep(5000);
                Random random = new();
                int weatherCode = random.Next(0, 0x0c);
                int oneMinute = random.Next(0, 1000);
                int tenMinute = random.Next(0, 1000);
                int deviceCode = random.Next(0, 4);
                byte[] buffer = [0x90,
                    Convert.ToByte(_controllerId),
                    0x06,
                    0x00
                    ,
                    Convert.ToByte(weatherCode)
                    ,
                    Convert.ToByte(oneMinute % (128 * 128) % 128)
                    ,
                    Convert.ToByte(oneMinute % (128 * 128) / 128)
                    ,
                    Convert.ToByte(oneMinute / 128 / 128)
                    ,
                    Convert.ToByte(tenMinute % (128 * 128) % 128)
                    ,
                    Convert.ToByte(tenMinute % (128 * 128) / 128)
                    ,
                    Convert.ToByte(tenMinute / 128 / 128)
                    ,
                    Convert.ToByte(deviceCode)
                    ,
                    0xff];
                Send(buffer);
            }
        }

        protected override bool Unpack(Socket socket, List<byte> buffer, ref int offset)
        {
            if (buffer.Count < 4 || buffer[0] != 0x81 || buffer[buffer.Count - 1] != 0xff)
            {
                _logger.LogWarning($"lamp protocol format error {buffer.Count}");
            }
            else
            {
                int protocolId = buffer[2];
                _logger.LogInformation($"lamp recv {socket.Handle} protocol:{protocolId:x2} buffer:{ByteConvert.ToHex(buffer, buffer.Count)}");
                byte[] responseBuffer = [0x90, Convert.ToByte(_controllerId), Convert.ToByte(protocolId), 0xff];
                Send(socket, responseBuffer);
                _logger.LogInformation($"lamp send {socket.Handle} protocol:{protocolId:x2} buffer:{ByteConvert.ToHex(responseBuffer, responseBuffer.Length)}");
            }
            offset += buffer.Count;
            return true;
        }

        public override void Close()
        {
            _source.Cancel();
            try
            {
                _task.Wait(_source.Token);
            }
            catch (OperationCanceledException)
            {

            }
            base.Close();
        }
    }
}
